/*
 *    Copyright (c) 2018-2025, lengleng All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the pig4cloud.com developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: lengleng (wangiegie@gmail.com)
 */
package com.pig4cloud.pigx.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import com.pig4cloud.pigx.common.customize.mongo.utils.MongoUtils;
import com.pig4cloud.pigx.common.customize.contants.MongoTableNameConstants;
import com.pig4cloud.pigx.common.customize.security.utils.SecurityUtil;
import com.pig4cloud.pigx.common.customize.utils.CommonUtil;
import com.pig4cloud.pigx.common.security.service.PigxUser;
import com.pig4cloud.pigx.user.entity.UserApiLockDuration;
import com.pig4cloud.pigx.user.mapper.UserApiLockDurationMapper;
import com.pig4cloud.pigx.user.mapstruct.UserApiLockDurationStruct;
import com.pig4cloud.pigx.user.mongo.entity.UserApiLockDurationMongo;
import com.pig4cloud.pigx.user.service.UserApiLockDurationService;
import lombok.AllArgsConstructor;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Objects;

/**
 * Api封禁时长配置表
 *
 * @since 2022-10-31 15:36:06
 */
@Service
@AllArgsConstructor
public class UserApiLockDurationServiceImpl extends ServiceImpl<UserApiLockDurationMapper, UserApiLockDuration> implements UserApiLockDurationService {

	private final MongoTemplate mongo;
	private final CommonUtil commonUtil;
	private final SecurityUtil securityUtil;

	/**
	 * 分页查询
	 *
	 * @param page      分页条件
	 * @param condition 查询条件
	 * @return {@link Page < UserApiLockDuration>}
	 * @since 2022/10/31 15:47
	 */
	@Override
	public Page<UserApiLockDuration> page(Page<UserApiLockDuration> page, UserApiLockDuration condition) {
		QueryWrapper<UserApiLockDuration> query = new QueryWrapper<>();
		query.lambda()
				.orderByDesc(UserApiLockDuration::getLockNum);

		return baseMapper.selectPage(page, query);
	}

	/**
	 * 根据id查询详情
	 *
	 * @param id id
	 * @return {@link Object}
	 * @since 2022/10/31 16:10
	 */
	@Override
	public UserApiLockDuration detail(Long id) {
		// 从mongodb中查询
		Criteria criteria = Criteria.where("id").is(id);
		Query query = Query.query(criteria);

		UserApiLockDurationMongo mongoEntity = mongo.findOne(query, UserApiLockDurationMongo.class);
		if (!Objects.isNull(mongoEntity)) {
			return UserApiLockDurationStruct.INSTANCE.mongo2Entity(mongoEntity);
		}

		// 没有时，尝试从mysql中查询
		UserApiLockDuration entity = baseMapper.selectById(id);
		if (Objects.isNull(entity)) {
			throw new RuntimeException("未能查询到数据");
		}

		return entity;
	}

	/**
	 * 新增
	 *
	 * @param param 参数
	 * @since 2022/10/31 16:19
	 */
	@Override
	@Transactional(rollbackFor = Throwable.class)
	public void insert(UserApiLockDuration param) {
		// 获取当前用户
		PigxUser user = SecurityUtil.getLoginUserNotNull();

		// 校验参数
		insertValid(param);

		// 组装参数
		UserApiLockDuration entity = new UserApiLockDuration();
		entity.setLockNum(param.getLockNum());
		entity.setDuration(param.getDuration());
		entity.setCreateName(user.getName());
		entity.setUpdateName(user.getName());
		securityUtil.initCreateAbout(entity);
		// 持久化到mysql
		if (baseMapper.insertIfNotConflict(entity) != 1) {
			String errorMsg = String.format("已存在封禁次数为%s的设置", entity.getLockNum());
			throw new RuntimeException(errorMsg);
		}

		UserApiLockDurationMongo mongoEntity = UserApiLockDurationStruct.INSTANCE.entity2Mongo(entity);
		// 保存到mongodb
		mongo.insert(mongoEntity, MongoTableNameConstants.USER_API_LOCK_DURATION);
	}

	/**
	 * 新增时校验参数
	 *
	 * @param param 参数
	 * @since 2022/10/31 16:23
	 */
	private static void insertValid(UserApiLockDuration param) {
		if (Objects.isNull(param.getLockNum())) {
			throw new RuntimeException("参数异常，lockNum为空");
		}
		if (param.getLockNum() < 1) {
			throw new RuntimeException("参数异常，lockNum不能小于1");
		}

		if (Objects.isNull(param.getDuration())) {
			throw new RuntimeException("参数异常，duration为空");
		}
	}

	/**
	 * 修改
	 *
	 * @param param 参数
	 * @since 2022/10/31 16:32
	 */
	@Override
	@Transactional(rollbackFor = Throwable.class)
	public void update(UserApiLockDuration param) {
		// 获取当前用户
		PigxUser user = SecurityUtil.getLoginUserNotNull();
		LocalDateTime now = LocalDateTime.now();

		// 校验参数
		updateValid(param);

		// 组装参数
		UserApiLockDuration entity = new UserApiLockDuration();
		entity.setId(param.getId());
		entity.setLockNum(param.getLockNum());
		entity.setDuration(param.getDuration());
		entity.setUpdateTime(now);
		entity.setUpdateBy(user.getId());
		entity.setUpdateName(user.getName());
		// 持久化到mysql
		if (baseMapper.updateIfNotConflict(entity) != 1) {
			String errorMsg = String.format("已存在封禁次数为%s的设置", entity.getLockNum());
			throw new RuntimeException(errorMsg);
		}

		// 更新mongodb
		Criteria criteria = Criteria.where("id").is(entity.getId());
		Query query = Query.query(criteria);
		Update update = MongoUtils.getUpdate(entity);

		UpdateResult updateResult = mongo.updateFirst(query, update, UserApiLockDurationMongo.class, MongoTableNameConstants.USER_API_LOCK_DURATION);
		if (updateResult.getMatchedCount() != 1) {
			throw new RuntimeException("操作失败");
		}
	}

	/**
	 * 修改时校验参数
	 *
	 * @param param 参数
	 * @since 2022/10/31 16:23
	 */
	private static void updateValid(UserApiLockDuration param) {
		if (Objects.isNull(param.getId())) {
			throw new RuntimeException("参数异常，id为空");
		}

		if (Objects.isNull(param.getLockNum())) {
			throw new RuntimeException("参数异常，lockNum为空");
		}
		if (param.getLockNum() < 1) {
			throw new RuntimeException("参数异常，lockNum不能小于1");
		}

		if (Objects.isNull(param.getDuration())) {
			throw new RuntimeException("参数异常，duration为空");
		}
	}

	/**
	 * 删除单条
	 *
	 * @param id id
	 * @since 2022/10/31 16:43
	 */
	@Override
	@Transactional(rollbackFor = Throwable.class)
	public void remove(Long id) {
		// 删除mysql
		if (baseMapper.deleteById(id) != 1) {
			throw new RuntimeException("操作失败");
		}

		// 删除mongo
		Criteria criteria = Criteria.where("id").is(id);
		Query query = Query.query(criteria);

		DeleteResult deleteResult = mongo.remove(query, UserApiLockDurationMongo.class, MongoTableNameConstants.USER_API_LOCK_DURATION);
		if (deleteResult.getDeletedCount() != 1) {
			throw new RuntimeException("操作失败");
		}
	}
}
